package com.hibase.core.page.service.pagemenucontent.impl;


import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.github.pagehelper.PageInfo;
import com.hibase.common.constant.LoginTypeContstants;
import com.hibase.common.exception.HibaseAssert;
import com.hibase.core.mybatis.service.BaseServiceImpl;
import com.hibase.core.mybatis.util.GenerateIdHelper;
import com.hibase.core.page.constant.MenuType;
import com.hibase.core.page.constant.PgeMenuContexnConstant;
import com.hibase.core.page.entity.menuxml.*;
import com.hibase.core.page.entity.pagemenuContent.PageMenuContent;
import com.hibase.core.page.entity.pagemenuContent.vo.PageMenuContentSearchVO;
import com.hibase.core.page.mapper.pagemenuContent.PageMenuContentMapper;
import com.hibase.core.page.service.pagemenucontent.PageMenuContentService;
import com.hibase.core.page.utils.FileUtils;
import com.hibase.core.page.utils.XStreamUtils;
import com.hibase.core.redis.util.RedisUtil;
import com.hibase.upms.constant.MdsMenuConstant;
import com.hibase.upms.constant.MenuPageType;
import com.hibase.upms.entity.menu.MdsMenu;
import com.hibase.upms.entity.rolemenu.MdsRoleMenu;
import com.hibase.upms.service.menu.MdsMenuService;
import com.hibase.upms.service.rolemenu.MdsRoleMenuService;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicReferenceArray;
import java.util.stream.Collectors;

/**
 * <p>
 * 菜单配置内容表 服务实现类
 * </p>
 *
 * @author junk
 * @since 2021-03-31
 */
@Log4j2
@Service
public class PageMenuContentServiceImpl extends BaseServiceImpl<PageMenuContentMapper, PageMenuContent> implements PageMenuContentService {

    @Autowired
    private MdsRoleMenuService mdsRoleMenuService;

    @Autowired
    private MdsMenuService mdsMenuService;
    
    @Autowired
    private RedisUtil redisUtil;
    
    @Autowired
    private PageMenuContentMapper pageMenuContentMapper;
    
    /**
     * 查询菜单配置内容表列表
     */
    @Override
    public PageInfo<PageMenuContent> selectPageMenuContentList(PageMenuContentSearchVO searchVO) {

        return super.page(searchVO, new QueryWrapper<PageMenuContent>());
    }

    /**
     * 改变菜单配置内容表记录
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void savePageMenuContent(PageMenuContent entity) {

        super.store(entity);
    }

    /**
     * 查询菜单配置内容表详情
     */
    @Override
    public PageMenuContent viewPageMenuContent(String id) {

        PageMenuContent entity = super.getById(id, true);

        return entity;
    }

    /**
     * 删除菜单配置内容表记录
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deletePageMenuContent(String id) {

        super.deleteBy(id);
    }


    /**
     * 导出菜单配置内容表记录
     */
    @Override
    @Transactional(readOnly = true, rollbackFor = Exception.class)
    public void exportPageMenuContent(PageMenuContentSearchVO searchVO, HttpServletResponse response) {

//        StringBuilder fileName = new StringBuilder();
//        fileName.append("export-");
//        fileName.append("PageMenuContent");
//        fileName.append(DateUtil.today());
//        Sheet sheet = null;
//        sheet = new Sheet(1, 1, PageMenuContentExportVO.class, fileName.toString(), null);
////todo
//        AttachmentUtils.exportExcelFile(response, sheet, null, fileName.toString());
    }

	@Override
    public List<MenuXmlVO> selectAllMenusContent(){
    	long startTime = System.currentTimeMillis();
    	//List<MenuXmlVO> menuList = (List<MenuXmlVO>) redisUtil.get(RedisKeyConstant.CACHE_USER_XML_MENU_KEY);
    	log.info("getMenuConfig-------------------使用时间[1-2=1]：" + (System.currentTimeMillis() - startTime) + "----------------------");
        List<MenuXmlVO> menuList = null;
    	//    	if (menuList != null && menuList.size() > 0) {
//    		 return menuList;
//    	}
    	//装ID
    	List<String> idList = new ArrayList<>();
    	//装重复ID
    	List<String> repectIdList = new ArrayList<>();
		//为空，查询XML
		QueryWrapper<PageMenuContent> queryWrapper = new QueryWrapper<PageMenuContent>();
		queryWrapper.eq("type", MenuType.MENU.getKey());
		List<PageMenuContent> menusContent = super.list(queryWrapper);
		
		List<String> menusXmlList = menusContent.stream().map(PageMenuContent::getContent).collect(Collectors.toList());
		List<MenusXmlVO> menus = menusXmlList.stream().map(p -> XStreamUtils.toBean(p, MenusXmlVO.class)).collect(Collectors.toList());
		
		log.info("getMenuConfig-------------------使用时间[1-2=2]：" + (System.currentTimeMillis() - startTime) + "----------------------");
		//判断ID是否重复
		boolean judgeRepect = false;
		judgeRepect = extracted(menus, idList, repectIdList, judgeRepect);
		log.info("getMenuConfig-------------------使用时间[1-2=3]：" + (System.currentTimeMillis() - startTime) + "----------------------");
		HibaseAssert.isFalse(judgeRepect, "请检查您的XML名称为：{} 配置，有重复ID,重复id:{}",menusContent.get(0).getName(), repectIdList);
		
		menuList = menus.stream().flatMap(p -> p.getMenuList().stream()).collect(Collectors.toList());
		// 设置parentID
		menuList.forEach(p->p.getChildren().forEach(c->c.getItemList().forEach(i->i.setParentId(p.getId()))));
		log.info("getMenuConfig-------------------使用时间[1-3]：" + (System.currentTimeMillis() - startTime) + "----------------------");
		
    	//把MENU XML 放入缓存
		//redisUtil.set(RedisKeyConstant.CACHE_USER_XML_MENU_KEY, menuList, RedisKeyConstant.CODE_SEQUENCE_EXPIRE);
        return menuList;
    }

    /**
     * @Title: PageMenuContentServiceImpl
     * @Description: 判断是否重复ID
     * @author TimBrian
     * @since Aug 24, 2021 2:18:57 PM
     * @param menuList
     * @param idList
     * @param repectIdList
     * @param judgeRepect
     * @return
     */
	private boolean extracted(List<MenusXmlVO> menuList, List<String> idList, List<String> repectIdList,
			boolean judgeRepect) {
		if (menuList != null && menuList.size() > 0) {
			for (MenuXmlVO menuXmlVO : menuList.get(0).getMenuList()) {
				if (idList.contains(menuXmlVO.getId())) {
					judgeRepect = true;
					repectIdList.add(menuXmlVO.getId());
					break;
				}
				log.debug("menuXmlVO::::::::::::::::::---" + menuXmlVO.getId());
				idList.add(menuXmlVO.getId());
				for (ItemMenuXmlVO itemMenuXmlVO : menuXmlVO.getChildren()) {
					if (idList.contains(itemMenuXmlVO.getId())) {
						judgeRepect = true;
						repectIdList.add(itemMenuXmlVO.getId());
						break;
					}
					log.debug("itemMenuXmlVO::::::::::::::::::===" + itemMenuXmlVO.getId());
					idList.add(itemMenuXmlVO.getId());
					for (ItemXmlVO itemXmlVO : itemMenuXmlVO.getItemList()) {
						if (idList.contains(itemXmlVO.getId())) {
							judgeRepect = true;
							repectIdList.add(itemXmlVO.getId());
							break;
						}
						log.debug("itemMenuXmlVO::::::::::::::::::+++" + itemXmlVO.getId());
						idList.add(itemXmlVO.getId());
					}
				}
			}
		}
		return judgeRepect;
	}
   

    @Override
    public List<PageMenuContent> getMenuContentByName(String name){
        QueryWrapper<PageMenuContent> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("name",name);
        List<PageMenuContent> menuList = super.list(queryWrapper);
        return menuList;
    }

	@Override
    @Transactional(rollbackFor = Exception.class)
    public void syncMenuByXml() {
        // step01 获取xml的页面
        List<MenuXmlVO> menuXmlList = this.selectAllMenusContent();
        List<MdsMenu> xmlVOToMenuList = this.menuXmlVOToMenu(menuXmlList);
        // step02 查询所有菜单
        List<MdsMenu> mdsMenuCollection = mdsMenuService.list();

        List<String> deleteCodes = mdsMenuCollection.stream().map(MdsMenu::getCode).collect(Collectors.toList());
        List<String> insertCodes = xmlVOToMenuList.stream().map(MdsMenu::getCode).collect(Collectors.toList());
        // step03 旧菜单存在  xml菜单不存在  删除
        if(CollUtil.isNotEmpty(xmlVOToMenuList)) {
            deleteCodes.removeAll(insertCodes);
        }
        if(CollUtil.isNotEmpty(deleteCodes)){
            List<String> deleteIds = mdsMenuCollection.stream().filter(menu -> deleteCodes.contains(menu.getCode())).map(MdsMenu::getId).collect(Collectors.toList());
            mdsMenuService.removeByIds(deleteIds);
            mdsRoleMenuService.remove(Wrappers.<MdsRoleMenu>lambdaQuery().in(MdsRoleMenu::getMenuId,deleteIds));
        }
        // step04 旧菜单不存在 xml菜单存在  新增
        if(CollUtil.isNotEmpty(mdsMenuCollection)){
            insertCodes.removeAll(mdsMenuCollection.stream().map(MdsMenu::getCode).collect(Collectors.toList()));
        }
        if(CollUtil.isNotEmpty(insertCodes) && CollUtil.isNotEmpty(xmlVOToMenuList)){
            // 通过xml生成menu
            List<MdsMenu> menuList = xmlVOToMenuList.stream()
                    .filter(vo -> insertCodes.contains(vo.getCode()))
                    .peek(menu ->{
                        xmlVOToMenuList.stream()
                                //得到当前节点的父节点
                                .filter(xmlMenu -> StrUtil.equals(xmlMenu.getId(), menu.getParentId()))
                                .findFirst()
                                //如果存在
                                .ifPresent(xmlMenu -> {
                                    //通过父节点找到旧节点
                                    mdsMenuCollection.stream()
                                            .filter(oldMenu -> StrUtil.equals(oldMenu.getCode(), xmlMenu.getCode()))
                                            .findFirst()
                                            //如旧节点已存在 则用旧节点
                                            .ifPresent(oldMenu -> {
                                                menu.setParentId(oldMenu.getId());
                                            });
                                });
                    }).collect(Collectors.toList());
            mdsMenuService.saveBatch(menuList);
        }
    }


    private List<MdsMenu> menuXmlVOToMenu(List<MenuXmlVO> menuXmlList){
        // 处理menuXml 数据到转换到mds_menu
        List<MdsMenu> menus = CollUtil.newArrayList();
        menuXmlList.forEach(p->{
            // 处理模块
            MdsMenu module = new MdsMenu();
            module.setId(GenerateIdHelper.idGenerate());
            module.setCode(p.getId());
            module.setName(p.getTitle());
            module.setIcon(p.getIcon());
            module.setSort(new BigDecimal(p.getSort()));
            module.setType(MenuType.MENU.getKey());
            module.setParentId(MdsMenuConstant.MENU_TREE_ROOT_ID);
            module.setUrl(null);
            module.setBeActive(Boolean.TRUE);
            module.setPath(p.getPath());
            module.setChildNumber(p.getChildren().size());  // 子节点数量
            module.setPageType(MenuPageType.PAGE_TYPE_CUSTOM.getName());
            module.setCreateTime(DateUtil.date());
            module.setBeDeleted(Boolean.FALSE);
            menus.add(module);
            //this.store(module);
            // 处理菜单
            p.getChildren().forEach(c->{
                MdsMenu menu = new MdsMenu();
                menu.setId(GenerateIdHelper.idGenerate());
                menu.setCode(c.getId());
                menu.setName(c.getId());
                menu.setSort(BigDecimal.ZERO);
                menu.setType(MenuType.MENU.getKey());
                menu.setParentId(module.getId());
                menu.setUrl(null);
                menu.setBeActive(Boolean.TRUE);
                menu.setChildNumber(c.getItemList().size());  // 子节点数量
                menu.setPageType(MenuPageType.PAGE_TYPE_CUSTOM.getName());
                menu.setCreateTime(DateUtil.date());
                menu.setBeDeleted(Boolean.FALSE);
                menus.add(menu);
                //this.store(menu);
                // 处理页面
                c.getItemList().forEach(i->{
                    MdsMenu page = new MdsMenu();
                    page.setId(GenerateIdHelper.idGenerate());
                    page.setCode(i.getId());
                    page.setName(i.getTitle());
                    page.setIcon(i.getIcon());
                    page.setSort(BigDecimal.ZERO);
                    page.setType(MenuType.PAGE.getKey());
                    page.setPageType(i.getBeCustom()? MenuPageType.PAGE_TYPE_CUSTOM.getName():MenuPageType.PAGE_TYPE_STANDARD.getName());
                    page.setParentId(menu.getId());
                    page.setUrl(null);
                    page.setBeActive(Boolean.TRUE);
                    page.setChildNumber(1);
                    page.setCreateTime(DateUtil.date());
                    page.setBeDeleted(Boolean.FALSE);
                    menus.add(page);
                    //this.store(page);
                    // 处理元素
                    if (i.getPermission()!=null){
                        // todo 暂时不支持外部
//                        ElementUrlXmlVO elementUrl = i.getPermission().getElementUrl();
//                        MdsMenu element = new MdsMenu();
//                        element.setId(GenerateIdHelper.idGenerate());
//                        element.setCode(elementUrl.getId());
//                        element.setName(elementUrl.getId());
//                        element.setIcon(null);
//                        element.setType(MenuType.ELEMENT.getKey());
//                        element.setPageType(null);
//                        element.setParentId(page.getId());
//                        element.setUrl(elementUrl.getValue());
//                        element.setBeActive(Boolean.TRUE);
//                        element.setCreateBy(AuthProvider.getLoginAccount());
//                        element.setCreateTime(DateUtil.date());
//                        element.setBeDeleted(Boolean.FALSE);
//                        menus.add(element);
                        List<OperationButtonXmlVO> operationButton = i.getPermission().getOperationButton();
                        List<MdsMenu> buttonMenu = operationButton.stream().map(o -> {
                            ElementUrlXmlVO elementButton = o.getElementUrl();
                            MdsMenu button = new MdsMenu();
                            button.setId(GenerateIdHelper.idGenerate());
                            button.setCode(o.getId());
                            button.setName(o.getId());
                            button.setPermission(elementButton.getId());
                            button.setIcon(null);
                            button.setSort(BigDecimal.ZERO);
                            button.setType(MenuType.ELEMENT.getKey());
                            button.setPageType(MenuPageType.PAGE_TYPE_CUSTOM.getName());
                            button.setParentId(page.getId());
                            button.setUrl(elementButton.getValue());
                            button.setBeActive(Boolean.TRUE);
                            button.setCreateTime(DateUtil.date());
                            button.setBeDeleted(Boolean.FALSE);
                            return button;
                        }).collect(Collectors.toList());
                        menus.addAll(buttonMenu);
                        //this.storeBatch(buttonMenu);
                    }

                });

            });
        });
        return menus;
    }

    /**
     * (non-Javadoc)
     * <p>Title: getPageXmlList</p>
     * <p>Description: 下载PAGE-XML</p>
     * @author TimBrian
     * @since 2021年11月5日 下午5:27:00
     * @param response
     */
	@Override
	public void downloadPageXmlList(HttpServletRequest request, HttpServletResponse response) throws IOException{
		// TODO Auto-generated method stub
		List<PageMenuContent> pageMenuContentList = pageMenuContentMapper.selectList(Wrappers.<PageMenuContent>lambdaQuery()
				.select(PageMenuContent :: getName, PageMenuContent :: getContent, PageMenuContent :: getType));
		HibaseAssert.isFalse(CollUtil.isEmpty(pageMenuContentList), "{} is empty coll", PgeMenuContexnConstant.DownloadType.PAGEXML);
		String targatPath = "D:\\pageConfig\\wms";
		AtomicReferenceArray<String> atomicRef = new AtomicReferenceArray<>(2);
		atomicRef.getAndSet(0, targatPath);
		// 查询2级目录列表
		List<String> menusXmlList = pageMenuContentList.stream().filter(e -> e.getType() != null && e.getType().equals(MenuType.MENU.getKey()))
					.map(e -> e.getContent()).collect(Collectors.toList());
		List<MenusXmlVO> menus = menusXmlList.stream().map(p -> XStreamUtils.toBean(p, MenusXmlVO.class)).collect(Collectors.toList());
		menus.stream().forEach(e -> {
			if (e.getId().equals(LoginTypeContstants.WMS)) {
				e.getMenuList().stream().forEach(p -> {
					atomicRef.set(0, targatPath + File.separator + p.getId().trim());
					p.getChildren().forEach(i -> {
						atomicRef.set(1, atomicRef.get(0) + File.separator + i.getId().trim());
						i.getItemList().forEach(j ->{
							pageMenuContentList.forEach(g -> {
								if (g.getName().equals(j.getId().trim())) {
									FileUtils.fileDownload1(new File(atomicRef.get(1)), g.getName() + ".xml", g.getContent().getBytes(), response);
								}
							});
						});
					});
				});
			}
		});
	}

	
}